﻿using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using GurLoader.Util;
using Imgur.Net.Auth;
using Newtonsoft.Json;

namespace GurLoader.Preferences
{
    public class GurLoaderPreferences : 
        ApplicationPreferencesBase<GurLoaderPreferences>, INotifyPropertyChanged
    {
        private bool openWhenComplete = true;
        private bool useAnonymousContext = true;
        private Key fullScreenCaptureKey = Key.None;
        private Key areaScreenCaptureKey = Key.None;
        private ModifierKeys fullScreenCaptureModifierKeys = ModifierKeys.None;
        private ModifierKeys areaScreenCaptureModifierKeys = ModifierKeys.None;
        private bool fullScreenCaptureEnabled = false;
        private bool areaScreenCaptureEnabled = false;
        private RegistrationTokenContext registartionTokens = null;

        private bool isAuthContextTypeChanged = false;

        private bool isDirty = false;

        private static readonly PropertyChangedEventArgs OpenWhenCompleteChangeArgs =
            ObservableHelper.CreateArgs<GurLoaderPreferences>(x => x.OpenWhenComplete);

        private static readonly PropertyChangedEventArgs UseAnonymousContextChangeArgs =
            ObservableHelper.CreateArgs<GurLoaderPreferences>(x => x.UseAnonymousContext);

        private static readonly PropertyChangedEventArgs IsDirtyChangeArgs =
            ObservableHelper.CreateArgs<GurLoaderPreferences>(x => x.IsDirty);

        private static readonly PropertyChangedEventArgs FullScreenCaptureKeyChangeArgs =
            ObservableHelper.CreateArgs<GurLoaderPreferences>(x => x.FullScreenCaptureKey);

        private static readonly PropertyChangedEventArgs FullScreenCaptureModifierKeysChangeArgs =
            ObservableHelper.CreateArgs<GurLoaderPreferences>(x => x.FullScreenCaptureModifierKeys);

        private static readonly PropertyChangedEventArgs AreaScreenCaptureKeyChangeArgs =
            ObservableHelper.CreateArgs<GurLoaderPreferences>(x => x.AreaScreenCaptureKey);

        private static readonly PropertyChangedEventArgs AreaScreenCaptureModifierKeysChangeArgs =
            ObservableHelper.CreateArgs<GurLoaderPreferences>(x => x.AreaScreenCaptureModifierKeys);

        private static readonly PropertyChangedEventArgs FullScreenCaptureEnabledChangeArgs =
            ObservableHelper.CreateArgs<GurLoaderPreferences>(x => x.FullScreenCaptureEnabled);

        private static readonly PropertyChangedEventArgs AreaScreenCaptureEnabledChangeArgs =
            ObservableHelper.CreateArgs<GurLoaderPreferences>(x => x.AreaScreenCaptureEnabled);

        private static readonly PropertyChangedEventArgs RegistrationTokensChangeArgs =
            ObservableHelper.CreateArgs<GurLoaderPreferences>(x => x.RegistrationTokens);

        public bool OpenWhenComplete
        {
            get { return openWhenComplete; }
            set
            {
                openWhenComplete = value;
                NotifyPropertyChanged(OpenWhenCompleteChangeArgs);
                IsDirty = true;
            }
        }

        public bool UseAnonymousContext
        {
            get { return useAnonymousContext; }
            set
            {
                useAnonymousContext = value;
                NotifyPropertyChanged(UseAnonymousContextChangeArgs);
                IsDirty = true;
                isAuthContextTypeChanged = true;
            }
        }

        [JsonIgnore]
        public virtual bool IsDirty
        {
            get { return isDirty; }
            private set
            {
                isDirty = value;
                NotifyPropertyChanged(IsDirtyChangeArgs);
            }
        }

        public ModifierKeys FullScreenCaptureModifierKeys
        {
            get { return fullScreenCaptureModifierKeys; }
            set
            {
                fullScreenCaptureModifierKeys = value;
                NotifyPropertyChanged(FullScreenCaptureModifierKeysChangeArgs);
                IsDirty = true;
            }
        }

        public Key FullScreenCaptureKey
        {
            get { return fullScreenCaptureKey; }
            set
            {
                fullScreenCaptureKey = value;
                NotifyPropertyChanged(FullScreenCaptureKeyChangeArgs);
                IsDirty = true;
            }
        }

        public bool FullScreenCaptureEnabled
        {
            get { return fullScreenCaptureEnabled; }
            set
            {
                fullScreenCaptureEnabled = value;
                NotifyPropertyChanged(FullScreenCaptureEnabledChangeArgs);
                IsDirty = true;
            }
        }

        public ModifierKeys AreaScreenCaptureModifierKeys
        {
            get { return areaScreenCaptureModifierKeys; }
            set
            {
                areaScreenCaptureModifierKeys = value;
                NotifyPropertyChanged(AreaScreenCaptureModifierKeysChangeArgs);
                IsDirty = true;
            }
        }

        public Key AreaScreenCaptureKey
        {
            get { return areaScreenCaptureKey; }
            set
            {
                areaScreenCaptureKey = value;
                NotifyPropertyChanged(AreaScreenCaptureKeyChangeArgs);
                IsDirty = true;
            }
        }
        
        public bool AreaScreenCaptureEnabled
        {
            get { return areaScreenCaptureEnabled; }
            set
            {
                areaScreenCaptureEnabled = value;
                NotifyPropertyChanged(AreaScreenCaptureEnabledChangeArgs);
                IsDirty = true;
            }
        }
        
        [JsonConverter(typeof(RegistrationTokenContextConverter<DefaultRegistrationTokenContext>))]
        public RegistrationTokenContext RegistrationTokens
        {
            get { return registartionTokens; }
            set
            {
                registartionTokens = value;
                NotifyPropertyChanged(RegistrationTokensChangeArgs);
                IsDirty = true;
            }
        }
        
        public virtual event PropertyChangedEventHandler PropertyChanged;

        protected virtual void NotifyPropertyChanged(PropertyChangedEventArgs args)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, args);
        }

        public virtual event EventHandler<AuthContextTypeChangedEventArgs> AuthContextTypeChanged;

        public override void Save(string fileName, bool suppressSavedEvent = false)
        {
            base.Save(fileName, suppressSavedEvent);
            FireAuthContextTypeChanged();
        }

        protected void FireAuthContextTypeChanged()
        {
            EventHandler<AuthContextTypeChangedEventArgs> handler = AuthContextTypeChanged;
            if (handler != null)
                handler(this, new AuthContextTypeChangedEventArgs(UseAnonymousContext));
        }
    }
}